/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file    usart.c
 * @brief   This file provides code for the configuration
 *          of the USART instances.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */
static uint8_t rec_complete_ua1 = 0;
static uint8_t rec_complete_ua2 = 0;
static uint8_t rec_complete_ua3 = 0;

static char ua1_rec_buffer[UART_RX_SIZE] = "{0}"; // 缓冲区
static char ua1_rec[UART_RX_SIZE]        = "bbn"; // 实际数据区
// static char ua2_rec_buffer[UART_RX_SIZE] = "{0}"; // 缓冲区
static char ua2_rec[UART_RX_SIZE] = "bbn"; // 实际数据区
// static char ua3_rec_buffer[UART_RX_SIZE] = "{0}"; // 缓冲区
static char ua3_rec[UART_RX_SIZE] = "bbn"; // 实际数据区

static char ua1_rx_buff = 0;
// static char ua2_rx_buff = 0;
// static char ua3_rx_buff = 0;

/* USER CODE END 0 */

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance          = USART1;
  huart1.Init.BaudRate     = 115200;
  huart1.Init.WordLength   = UART_WORDLENGTH_8B;
  huart1.Init.StopBits     = UART_STOPBITS_1;
  huart1.Init.Parity       = UART_PARITY_NONE;
  huart1.Init.Mode         = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK) {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  UART_Start_Receive_DMA(&huart1, (uint8_t *)&ua1_rx_buff, 1);
  /* USER CODE END USART1_Init 2 */
}
/* USART2 init function */

void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance          = USART2;
  huart2.Init.BaudRate     = 115200;
  huart2.Init.WordLength   = UART_WORDLENGTH_8B;
  huart2.Init.StopBits     = UART_STOPBITS_1;
  huart2.Init.Parity       = UART_PARITY_NONE;
  huart2.Init.Mode         = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK) {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */
}

void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if (uartHandle->Instance == USART1) {
    /* USER CODE BEGIN USART1_MspInit 0 */

    /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin       = GPIO_PIN_9 | GPIO_PIN_10;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_NOPULL;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance                 = DMA2_Stream2;
    hdma_usart1_rx.Init.Channel             = DMA_CHANNEL_4;
    hdma_usart1_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc              = DMA_MINC_DISABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode                = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority            = DMA_PRIORITY_MEDIUM;
    hdma_usart1_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle, hdmarx, hdma_usart1_rx);

    /* USART1_TX Init */
    hdma_usart1_tx.Instance                 = DMA2_Stream7;
    hdma_usart1_tx.Init.Channel             = DMA_CHANNEL_4;
    hdma_usart1_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode                = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority            = DMA_PRIORITY_MEDIUM;
    hdma_usart1_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle, hdmatx, hdma_usart1_tx);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
    /* USER CODE BEGIN USART1_MspInit 1 */

    /* USER CODE END USART1_MspInit 1 */
  } else if (uartHandle->Instance == USART2) {
    /* USER CODE BEGIN USART2_MspInit 0 */

    /* USER CODE END USART2_MspInit 0 */
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    GPIO_InitStruct.Pin       = GPIO_PIN_2 | GPIO_PIN_3;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_NOPULL;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USER CODE BEGIN USART2_MspInit 1 */
    /* USER CODE END USART2_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
{

  if (uartHandle->Instance == USART1) {
    /* USER CODE BEGIN USART1_MspDeInit 0 */

    /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);

    /* USART1 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmarx);
    HAL_DMA_DeInit(uartHandle->hdmatx);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
    /* USER CODE BEGIN USART1_MspDeInit 1 */

    /* USER CODE END USART1_MspDeInit 1 */
  } else if (uartHandle->Instance == USART2) {
    /* USER CODE BEGIN USART2_MspDeInit 0 */

    /* USER CODE END USART2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();

    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2 | GPIO_PIN_3);

    /* USER CODE BEGIN USART2_MspDeInit 1 */
    /* USER CODE END USART2_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

//bug: 请不要在中断或回调函数中使用该函数，否则可能引发死锁
// void USART_SendString(UART_HandleTypeDef *pUSARTx, char *DataString)
// {
//   HAL_UART_Transmit_DMA(pUSARTx, (uint8_t *)DataString, strlen(DataString)); // 每次发送字符串的一个字符
//   while (__HAL_UART_GET_FLAG(pUSARTx, UART_FLAG_TC) != SET);
//   __HAL_UART_CLEAR_FLAG(pUSARTx, UART_FLAG_TC);
// }

//note: 请不要在中断或回调函数中使用该函数，否则可能引发死锁
void USART_Printf(UART_HandleTypeDef *pUSARTx, char *format, ...)
{
  char String[UART_TX_SIZE] = {0};
  va_list arg;
  va_start(arg, format);
  vsprintf(String, format, arg);
  va_end(arg);

  HAL_UART_Transmit_DMA(pUSARTx, (uint8_t *)String, strlen(String));
  while (__HAL_UART_GET_FLAG(pUSARTx, UART_FLAG_TC) != SET);
  __HAL_UART_CLEAR_FLAG(pUSARTx, UART_FLAG_TC);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance != USART1) return; // 仅处理USART1 RX的DMA完成

  static uint16_t i = 0;
  __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE); // 发送字符前清空标志位（否则缺失字符串的第一个字符）

  /*接收数据，一次接收一个字节，最多接收前UART0_RX_SIZE个字符，直到收到'\n'为止（即使数据本身超过长度也能接收到数据的最后一个字符，实际接收的最大字符长度取决于设置ua0_rec_buffer和UART0_RX_SIZE的大小，与DMA和UART无关）*/
  if (i < UART_RX_SIZE) ua1_rec_buffer[i++] = ua1_rx_buff;

  /*收到'\n'时，完成数据接收*/
  if (ua1_rx_buff == '\n') {

    if (ua1_rec_buffer[i - 2] == '\r') ua1_rec_buffer[i - 2] = '\0';
    ua1_rec_buffer[i - 1] = '\0';
    strcpy(ua1_rec, ua1_rec_buffer); // 数据转存
    memset(ua1_rec_buffer, 0, sizeof(ua1_rec_buffer)); // 清除缓存

    rec_complete_ua1 = 1;
    i                = 0;
  }

  UART_Start_Receive_DMA(&huart1, (uint8_t *)&ua1_rx_buff, 1);
}

uint8_t USART_Get_recState(UART_HandleTypeDef *pUSARTx)
{
  uint8_t state       = 0;
  uint32_t USART_ADDR = (uint32_t)pUSARTx->Instance;
  switch (USART_ADDR) {
    // USART1
    case (uint32_t)USART1: {
      state            = rec_complete_ua1;
      rec_complete_ua1 = 0;
      break;
    }
    // USART2
    case (uint32_t)USART2: {
      state            = rec_complete_ua2;
      rec_complete_ua2 = 0;
      break;
    }
    // USART3
    case (uint32_t)USART3: {
      state            = rec_complete_ua3;
      rec_complete_ua3 = 0;
      break;
    }
  }

  return state;
}

char *USART_ReturnRxData(UART_HandleTypeDef *pUSARTx)
{
  uint32_t USART_ADDR = (uint32_t)pUSARTx->Instance;
  switch (USART_ADDR) {
    // USART1
    case (uint32_t)USART1: {
      return ua1_rec;
    }
    // USART2
    case (uint32_t)USART2: {
      return ua2_rec;
    }
    // USART3
    case (uint32_t)USART3: {
      return ua3_rec;
    }
    default:
      return 0;
  }
}
/* USER CODE END 1 */
